using System;
using OfficeOpenXml.FormulaParsing.Excel.Functions.Math;
using UnityEngine;
using UnityEngine.Rendering.HighDefinition;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using UnityEditor.Rendering.HighDefinition;
using UnityEditor;

public class BloomSeparatedCompute : CustomPass
{
    [System.Serializable]
    public class BloomSettings
    {
        // [Range(0, 8)] public int downSampleLevels = 5;

        [Range(0, 3)] public float intensity = 1.0f;

        [Range(0, 16)] public float blurRadius = 1.0f;

        [Range(0, 2)] public float threshold = 0.7f;
    }


    [Header("星铁——角色Bloom设置")] public BloomSettings characterBloom = new BloomSettings();
    [Header("星铁——场景Bloom设置")] public BloomSettings sceneBloom = new BloomSettings();


    [Range(0, 8)] public int downSampleLevels = 5;
    //
    // [Range(0, 3)] public float intensity = 1.0f;
    //
    // [Range(0, 16)] public float blurRadius = 1.0f;
    //
    // [Range(0, 2)] public float threshold = 0.7f;

    Material downSampleMaterial;
    Material upSampleMaterial;
    Material blitCopyMaterial;
    Material thresholdExtractMaterial;

    private const int MAX_BUFFER_COUNT = 8;


    //
    // RTHandle[] downSampleBuffers;
    // RTHandle[] hoSampleBuffer;
    // private RTHandle[] downSampleBuffers;
    // RTHandle thresholdBuffer;

    // 为角色和场景分别创建缓冲区
    RTHandle[] downSampleBuffers;
    RTHandle[] hoSampleBuffer;
    RTHandle[] verSampleBuffer;
    RTHandle thresholdBuffer;
   
    RTHandle finalBuffer;

    private int kernelIndex;
    private uint threadGroupSizeX, threadGroupSizeY, threadGroupSizeZ;
    // 添加Compute Shader引用
    public ComputeShader thresholdExtractCompute;
    public ComputeShader downSampleCompute;
    public ComputeShader upSampleCompute;
    public ComputeShader compsiteCompute;

    // 确保在Scene视图中也执行
    protected override bool executeInSceneView => true;

    // Trick to always include these shaders in build
    [SerializeField, HideInInspector] Shader downSampleShader;
    [SerializeField, HideInInspector] Shader upSampleShader;
    [SerializeField, HideInInspector] Shader blitCopyShader;
    [SerializeField, HideInInspector] Shader thresholdExtractShader;


    static class ShaderID
    {
        public static readonly int _Source = Shader.PropertyToID("_Source");
        public static readonly int _Source1 = Shader.PropertyToID("_Source1");
        public static readonly int _Source2 = Shader.PropertyToID("_Source2");
        public static readonly int _Source3 = Shader.PropertyToID("_Source3");
        public static readonly int _Source4 = Shader.PropertyToID("_Source4");

        //====场景==========
        public static readonly int _SceneSource1 = Shader.PropertyToID("_SceneSource1");
        public static readonly int _SceneSource2 = Shader.PropertyToID("_SceneSource2");
        public static readonly int _SceneSource3 = Shader.PropertyToID("_SceneSource3");
        public static readonly int _SceneSource4 = Shader.PropertyToID("_SceneSource4");
        //====场景==========


        public static readonly int _Intensity = Shader.PropertyToID("_Intensity");
        public static readonly int _Offset = Shader.PropertyToID("_Offset");
        public static readonly int _ViewPortSize = Shader.PropertyToID("_ViewPortSize");
        public static readonly int _Size = Shader.PropertyToID("_Size");
        public static readonly int _UpSize = Shader.PropertyToID("_UpSize");
        public static readonly int _Threshold = Shader.PropertyToID("_Threshold");
        public static readonly int _BufferCount = Shader.PropertyToID("_BufferCount");
        public static readonly int _SceneViewMode = Shader.PropertyToID("_SceneViewMode");

        public static readonly int _CharacterMaskTex = Shader.PropertyToID("_CharacterMaskTex");
        public static readonly int _IsCharacterBloom = Shader.PropertyToID("_IsCharacterBloom");
    }

    protected override void Setup(ScriptableRenderContext renderContext, CommandBuffer cmd)
    {
        
        if (downSampleShader == null)
            downSampleShader = Shader.Find("Hidden/Fullscreen/DownSample");
        if (upSampleShader == null)
            upSampleShader = Shader.Find("Hidden/Fullscreen/UpSampleSeparated");
        if (blitCopyShader == null)
            blitCopyShader = Shader.Find("Hidden/Fullscreen/BlitCopy");
        if (thresholdExtractShader == null)
            thresholdExtractShader = Shader.Find("Hidden/Fullscreen/ThresholdExtractSeparated");


        if (downSampleShader != null)
            downSampleMaterial = CoreUtils.CreateEngineMaterial(downSampleShader);
        if (upSampleShader != null)
            upSampleMaterial = CoreUtils.CreateEngineMaterial(upSampleShader);
        if (blitCopyShader != null)
            blitCopyMaterial = CoreUtils.CreateEngineMaterial(blitCopyShader);
        if (thresholdExtractShader != null)
            thresholdExtractMaterial = CoreUtils.CreateEngineMaterial(thresholdExtractShader);


        // 创建阈值提取缓冲区
        thresholdBuffer = RTHandles.Alloc(
            Vector2.one * 0.5f,
            slices: 1, // 明确指定为1
            dimension: TextureDimension.Tex2D, // ✅ 关键修改：使用Tex2D
            colorFormat: GraphicsFormat.B10G11R11_UFloatPack32,
            enableRandomWrite: true,
            useDynamicScale: true,
            name: "thresholdBuffer"
        );

   

        // int sampleLevels = Math.Max(characterBloom.downSampleLevels, sceneBloom.downSampleLevels);
        int sampleLevels = downSampleLevels;
        // 创建降采样和升采样缓冲区,这里可以用最大的
        downSampleBuffers = new RTHandle[MAX_BUFFER_COUNT];
        hoSampleBuffer = new RTHandle[MAX_BUFFER_COUNT];
        verSampleBuffer = new RTHandle[MAX_BUFFER_COUNT];
        finalBuffer  = RTHandles.Alloc(
            Vector2.one ,
            slices: 1, // 明确指定为1
            dimension: TextureDimension.Tex2D, // 使用Tex2D
            colorFormat: GraphicsFormat.B10G11R11_UFloatPack32,
            enableRandomWrite: true, // ← 关键：添加这个
            useDynamicScale: true,
            name:"finalBuffer"
        );


        for (int i = 0; i < sampleLevels; i++)
        {
            float scale = 1.0f / Mathf.Pow(2, i + 2); //前面取阈值已经缩小过了，这里多缩小一倍

            // 角色降采样缓冲区
            downSampleBuffers[i] = RTHandles.Alloc(
                Vector2.one * scale,
                slices: 1, // 明确指定为1
                dimension: TextureDimension.Tex2D, // 使用Tex2D
                colorFormat: GraphicsFormat.B10G11R11_UFloatPack32,
                enableRandomWrite: true, // ← 关键：添加这个
                useDynamicScale: true,
                name: $"DownSampleBuffer_{i}"
            );

            hoSampleBuffer[i] = RTHandles.Alloc(
                Vector2.one * scale,
                slices: 1,
                dimension: TextureDimension.Tex2D,
                colorFormat: GraphicsFormat.B10G11R11_UFloatPack32,
                enableRandomWrite: true, // ← 关键：添加这个
                useDynamicScale: true,
                name: $"HoSampleBuffer_{i}"
            );

            verSampleBuffer[i] = RTHandles.Alloc(
                Vector2.one * scale,
                slices: 1,
                dimension: TextureDimension.Tex2D,
                colorFormat: GraphicsFormat.B10G11R11_UFloatPack32,
                enableRandomWrite: true, // ← 关键：添加这个
                useDynamicScale: true,
                name: $"VerSampleBuffer_{i}"
            );

         
            
        }
    }

    protected override void Execute(CustomPassContext ctx)
    {
        if (downSampleMaterial == null || upSampleMaterial == null || blitCopyMaterial == null ||
            thresholdExtractMaterial == null)
            return;

        // 只在主相机或场景视图中渲染
        if (ctx.hdCamera.camera != Camera.main && ctx.hdCamera.camera.cameraType != CameraType.SceneView)
            return;

        RTHandle source = (targetColorBuffer == TargetBuffer.Camera)
            ? ctx.cameraColorBuffer
            : ctx.customColorBuffer.Value;

        // 检测是否为Scene视图
        bool isSceneView = ctx.hdCamera.camera.cameraType == CameraType.SceneView;

        // 第一步：分别提取角色和场景的阈值
        PerformComputeThresholdExtract(ctx, source, isSceneView);

        PerformDownSample(ctx); 
        PerformUpSample(ctx); 
        // 第四步：合成到最终目标
        // Compsite(ctx, finalBuffer, source);
    }
    void DrawToCamera(CustomPassContext ctx, RTHandle source, RTHandle destination)
    {
        // if (blitCopyMaterial == null) return;
        //
        // // 设置材质纹理
        // blitCopyMaterial.SetTexture(ShaderID._Source, source);
        //
        // // 使用全屏四边形绘制到相机缓冲区
        // CoreUtils.SetRenderTarget(ctx.cmd, destination);
        // ctx.cmd.SetViewport(ctx.hdCamera.camera.pixelRect); // 设置全屏视口
        //
        // // 绘制全屏三角形
        // // CoreUtils.DrawFullScreen(ctx.cmd, blitCopyMaterial);
        // var properties = new MaterialPropertyBlock();
        //
        // HDUtils.DrawFullScreen(ctx.cmd, upSampleMaterial, destination, properties, shaderPassId: 2);
        // if (downSampleBuffers[1] != null)
        //     properties.SetTexture(ShaderID._Source1, downSampleBuffers[1]);
        // if (downSampleBuffers.Length > 2 && downSampleBuffers[2] != null)
        //     properties.SetTexture(ShaderID._Source2, downSampleBuffers[2]);
        // if (downSampleBuffers.Length > 3 && downSampleBuffers[3] != null)
        //     properties.SetTexture(ShaderID._Source3, downSampleBuffers[3]);
        // if (downSampleBuffers.Length > 4 && downSampleBuffers[4] != null)
        //     properties.SetTexture(ShaderID._Source4, downSampleBuffers[4]);
        //
        // // 或者使用 Blit
        // ctx.cmd.Blit(source, destination, blitCopyMaterial, 0);
    }
    void PerformComputeThresholdExtract(CustomPassContext ctx, RTHandle source, bool isSceneView)
    {
        // 提前退出：Compute Shader未设置
        if (thresholdExtractCompute == null)
            return;

        // 一次性初始化
        kernelIndex = thresholdExtractCompute.FindKernel("CS_ThresholdExtract");
        thresholdExtractCompute.GetKernelThreadGroupSizes(kernelIndex, out threadGroupSizeX, out threadGroupSizeY,
            out threadGroupSizeZ);

        Vector2Int textureSize = thresholdBuffer.GetScaledSize(thresholdBuffer.rtHandleProperties.currentViewportSize);

        // 设置纹理
        ctx.cmd.SetComputeTextureParam(thresholdExtractCompute, kernelIndex, "_OutputTexture", thresholdBuffer);
        ctx.cmd.SetComputeTextureParam(thresholdExtractCompute, kernelIndex, "_Source", source);

        // 设置参数
        ctx.cmd.SetComputeFloatParam(thresholdExtractCompute, "_Threshold_Character", characterBloom.threshold);
        ctx.cmd.SetComputeFloatParam(thresholdExtractCompute, "_Threshold_Scene", sceneBloom.threshold);
        ctx.cmd.SetComputeFloatParam(thresholdExtractCompute, "_Intensity", 1.0f);
        ctx.cmd.SetComputeFloatParam(thresholdExtractCompute, "_SceneViewMode", isSceneView ? 1.0f : 0.0f);
        ctx.cmd.SetComputeFloatParam(thresholdExtractCompute, "_IsCharacterBloom", 1.0f); // 总是 true
        ctx.cmd.SetComputeVectorParam(thresholdExtractCompute, "_TextureSize",
            new Vector4(textureSize.x, textureSize.y, 0, 0));

        // 计算线程组数量
        int threadGroupsX = Mathf.CeilToInt(textureSize.x / (float)threadGroupSizeX);
        int threadGroupsY = Mathf.CeilToInt(textureSize.y / (float)threadGroupSizeY);

        // 调度计算
        ctx.cmd.DispatchCompute(thresholdExtractCompute, kernelIndex, threadGroupsX, threadGroupsY, 1);

#if UNITY_EDITOR
        // Debug.Log("Compute Shader 阈值提取");
#endif
    }
    void PerformDownSample(CustomPassContext ctx)
    {
        RTHandle currentSource = thresholdBuffer;

        // 提前获取Compute Shader和Kernel索引（建议缓存）
        int kernel = downSampleCompute.FindKernel("CS_DownSampleBoxBlur");

        for (int i = 0; i < downSampleLevels; i++)
        {
            RTHandle targetBuffer = downSampleBuffers[i];
            Vector2Int sourceSize = currentSource.GetScaledSize(currentSource.rtHandleProperties.currentViewportSize);
            Vector2Int destSize = targetBuffer.GetScaledSize(targetBuffer.rtHandleProperties.currentViewportSize);

            // 设置纹理
            ctx.cmd.SetComputeTextureParam(downSampleCompute, kernel, "_Source", currentSource);
            ctx.cmd.SetComputeTextureParam(downSampleCompute, kernel, "_Destination", targetBuffer);

            // 设置参数
            ctx.cmd.SetComputeVectorParam(downSampleCompute, "_Offset",
                new Vector4(1.0f / sourceSize.x, 1.0f / sourceSize.y, 0, 0));
            ctx.cmd.SetComputeVectorParam(downSampleCompute, "_Size",
                new Vector4(i, i, 0, 0));
       
            // ctx.cmd.SetComputeVectorParam(downSampleCompute, "_RTHandleScale",
            //     currentSource.rtHandleProperties.rtHandleScale);

            // 计算线程组数量并调度
            int groupsX = Mathf.CeilToInt(sourceSize.x / (float)threadGroupSizeX);
            int groupsY = Mathf.CeilToInt(sourceSize.y / (float)threadGroupSizeY);
            ctx.cmd.DispatchCompute(downSampleCompute, kernel, groupsX, groupsY, 1);

            currentSource = targetBuffer;
        }
    }


    void PerformUpSample(CustomPassContext ctx)
    {
        if (upSampleCompute == null)
        {
            Debug.LogError("UpSample Compute Shader is not assigned!");
            return;
        }

        int HoBlur_kernel = upSampleCompute.FindKernel("CS_HoBlur");
        int VerBlur_kernel = upSampleCompute.FindKernel("CS_VerBlur");
        const int GROUP_SIZE = 8;
        // 水平模糊
        for (int i = 1; i < downSampleLevels; i++)
        {
            RTHandle currentSource = downSampleBuffers[i];
            RTHandle targetBuffer = hoSampleBuffer[i];
            Vector2Int sourceSize = currentSource.GetScaledSize(currentSource.rtHandleProperties.currentViewportSize);
            Vector2Int destSize = targetBuffer.GetScaledSize(targetBuffer.rtHandleProperties.currentViewportSize);

            // 设置纹理
            ctx.cmd.SetComputeTextureParam(upSampleCompute, HoBlur_kernel, "_Source", currentSource);
            ctx.cmd.SetComputeTextureParam(upSampleCompute, HoBlur_kernel, "_Destination", targetBuffer);
            ctx.cmd.SetComputeVectorParam(upSampleCompute,"_UpSize", new Vector4(i, i, 0, 0));

            // 设置参数
            ctx.cmd.SetComputeVectorParam(upSampleCompute, "_Offset_Character",
                new Vector4(characterBloom.blurRadius / sourceSize.x, characterBloom.blurRadius / sourceSize.y, 0, 0));
            ctx.cmd.SetComputeVectorParam(upSampleCompute, "_Offset_Scene",
                new Vector4(sceneBloom.blurRadius / sourceSize.x, sceneBloom.blurRadius / sourceSize.y, 0, 0));
            
            ctx.cmd.SetComputeVectorParam(upSampleCompute, "_Size", new Vector4(i, i, 0, 0));
          
            ctx.cmd.SetComputeFloatParam(upSampleCompute, "_Intensity_Character", characterBloom.intensity);
            ctx.cmd.SetComputeFloatParam(upSampleCompute, "_Intensity_Scene", sceneBloom.intensity);

            // 计算线程组数量并调度
            int groupsX = Mathf.CeilToInt(sourceSize.x / (float)GROUP_SIZE);
            int groupsY = Mathf.CeilToInt(sourceSize.y / (float)GROUP_SIZE);
            ctx.cmd.DispatchCompute(upSampleCompute, HoBlur_kernel, groupsX, groupsY, 1);
        }
        // return;
        // 垂直模糊
        for (int i = 1; i < downSampleLevels; i++)
        {
            RTHandle currentSource = hoSampleBuffer[i];
            RTHandle targetBuffer = verSampleBuffer[i];
            Vector2Int sourceSize = currentSource.GetScaledSize(currentSource.rtHandleProperties.currentViewportSize);
            Vector2Int destSize = targetBuffer.GetScaledSize(targetBuffer.rtHandleProperties.currentViewportSize);

            // 设置纹理
            ctx.cmd.SetComputeTextureParam(upSampleCompute, VerBlur_kernel, "_Source", currentSource);
            ctx.cmd.SetComputeTextureParam(upSampleCompute, VerBlur_kernel, "_Destination", targetBuffer);
            ctx.cmd.SetComputeVectorParam(upSampleCompute,"_UpSize", new Vector4(i, i, 0, 0));

            // 设置参数
            ctx.cmd.SetComputeVectorParam(upSampleCompute, "_Offset_Character",
                new Vector4(characterBloom.blurRadius / sourceSize.x,characterBloom. blurRadius / sourceSize.y, 0, 0));
            ctx.cmd.SetComputeVectorParam(upSampleCompute, "_Offset_Scene",
                new Vector4(sceneBloom.blurRadius / sourceSize.x, sceneBloom.blurRadius / sourceSize.y, 0, 0));

            ctx.cmd.SetComputeVectorParam(upSampleCompute, "_Size",
                new Vector4(i, i, 0, 0));
    
            ctx.cmd.SetComputeFloatParam(upSampleCompute, "_Intensity_Character",  characterBloom.intensity);
            ctx.cmd.SetComputeFloatParam(upSampleCompute, "_Intensity_Scene", sceneBloom.intensity);


            // 计算线程组数量并调度
            int groupsX = Mathf.CeilToInt(sourceSize.x / (float)GROUP_SIZE);
            int groupsY = Mathf.CeilToInt(sourceSize.y / (float)GROUP_SIZE);
            ctx.cmd.DispatchCompute(upSampleCompute, VerBlur_kernel, groupsX, groupsY, 1);
        }
    }

    void Compsite(CustomPassContext ctx, RTHandle finalTarget,RTHandle source)
    {
        if (compsiteCompute == null)
        {
            Debug.LogError("Compsite Compute Shader is not assigned!");
            return;
        }
        int Compsite_kernel = compsiteCompute.FindKernel("CS_Compsite");
        if (Compsite_kernel < 0)
        {
            Debug.LogError("CS_Compsite kernel not found in Compute Shader!");
            return;
        }
        Vector2Int sourceSize = finalTarget.GetScaledSize(finalTarget.rtHandleProperties.currentViewportSize);
        const int GROUP_SIZE = 8;
        // 传递角色Bloom缓冲区
        // 设置纹理
        
        ctx.cmd.SetComputeTextureParam(compsiteCompute, Compsite_kernel, "_Destination", finalTarget);
        ctx.cmd.SetComputeTextureParam(compsiteCompute, Compsite_kernel, "_Source", source);

        // 传递角色Bloom缓冲区
        if (verSampleBuffer.Length > 1 && verSampleBuffer[1] != null)
            ctx.cmd.SetComputeTextureParam(compsiteCompute, Compsite_kernel, "_Source1",
                verSampleBuffer[1]);
        if (verSampleBuffer.Length > 2 && verSampleBuffer[2] != null)
            ctx.cmd.SetComputeTextureParam(compsiteCompute, Compsite_kernel, "_Source2",
                verSampleBuffer[2]);
        if (verSampleBuffer.Length > 3 && verSampleBuffer[3] != null)
            ctx.cmd.SetComputeTextureParam(compsiteCompute, Compsite_kernel, "_Source3",
                verSampleBuffer[3]);
        if (verSampleBuffer.Length > 4 && verSampleBuffer[4] != null)
            ctx.cmd.SetComputeTextureParam(compsiteCompute, Compsite_kernel, "_Source4",
                verSampleBuffer[4]);
        //
        ctx.cmd.SetComputeIntParam(compsiteCompute,"_BufferCount", Mathf.Min(verSampleBuffer.Length - 1, 4));
        ctx.cmd.SetComputeFloatParam(compsiteCompute, "_Intensity_Character", characterBloom.intensity);
        ctx.cmd.SetComputeFloatParam(compsiteCompute, "_Intensity_Scene", sceneBloom.intensity);
        // Vector2Int textureSize = output.GetScaledSize(output.rtHandleProperties.currentViewportSize);
        //
        // ctx.cmd.SetComputeVectorParam(thresholdExtractCompute, "_TextureSize",
        //     new Vector4(textureSize.x, textureSize.y, 0, 0));
        // // 计算线程组数量并调度
        int groupsX = Mathf.CeilToInt(sourceSize.x / (float)GROUP_SIZE);
        int groupsY = Mathf.CeilToInt(sourceSize.y / (float)GROUP_SIZE);
        ctx.cmd.DispatchCompute(compsiteCompute, Compsite_kernel, groupsX, groupsY, 1);
    }


    protected override void Cleanup()
    {
        CoreUtils.Destroy(downSampleMaterial);
        CoreUtils.Destroy(upSampleMaterial);
        CoreUtils.Destroy(blitCopyMaterial);
        CoreUtils.Destroy(thresholdExtractMaterial);
        thresholdBuffer?.Release();
        ReleaseBufferArray(downSampleBuffers);
        ReleaseBufferArray(hoSampleBuffer);
        ReleaseBufferArray(verSampleBuffer);
     
        finalBuffer.Release();
    }

    void ReleaseBufferArray(RTHandle[] buffers)
    {
        if (buffers != null)
        {
            for (int i = 0; i < buffers.Length; i++)
            {
                buffers[i]?.Release();
            }
        }
    }
}